package architecture;
import Prism.core.Architecture;
import Prism.core.Component;
import Prism.core.Connector;
import Prism.core.Port;
import Prism.core.PrismConstants;
import Prism.extensions.port.ExtensiblePort;
import Prism.extensions.port.distribution.SocketDistribution;
import basicTypes.C4Constant;

import component.CustomerSupport;
import component.TransConsistCheck;

public class C4main {
	
	//Variable Initialize
	Architecture c4Architecture;
	ExtensiblePort ConnNossTransManagerConnRequestPort;
	ExtensiblePort nossTransManagerConnRequestPort;
	ExtensiblePort transConsistCheckConnReplyPortRequestPort;
	TransConsistCheck transConsistCheck; 
	
	public C4main() {
		
		// Create an architecture for the C4.
		c4Architecture = new Architecture();

		transConsistCheckStart();
		
		// Weld and open socket for TaskProcessorGUI and customer Support
		customerSupportStart();
		
		// Start C4
		c4Architecture.start();
		
		// Connect the connector request port to the onlineDatabaseConn.
		ConnNossTransManagerConnRequestPort.connect(C4Constant.hostname, C4Constant.onlineDatabasePort);

		// Connect the connector request port to the nossTransManagerConn.
		nossTransManagerConnRequestPort.connect(C4Constant.hostname, C4Constant.nossTransManagerPort);
		
		// Connect the connector request port to the transConsistCheckConn.
		transConsistCheckConnReplyPortRequestPort.connect(C4Constant.hostname, C4Constant.transconsistCheckPort);
		
		//Test Request
		transConsistCheck.getUserData("2132548799");
	}
	
	private void transConsistCheckStart() {
		// Create Implementation
		transConsistCheck = new TransConsistCheck();
	
        // Create transConsistCheck Component
    	Component transConsistCheckComponent = new Component();
		
		// Create transConsistCheck Component's implementation
    	transConsistCheckComponent.setImplementation(transConsistCheck);
    	
		// Create a connector(nossTransManagerConn)
		Connector nossTransManagerConnClient = new Connector();


	/*
	 * ConnNossTransManager Client
	 */
		// Add a port to the ConnNossTransManager for sending requests.
		Port ConnNossTransManagerRequestPort = new Port(PrismConstants.REQUEST);
		nossTransManagerConnClient.addPort(ConnNossTransManagerRequestPort);

		// Create a connector(onLineDatabaseConn)
		Connector onLineDatabaseConnClient = new Connector();
		
		// Add a port to the nossTransManagerConn for receiving requests.
		Port onLineDatabaseConnReplyPort = new Port(PrismConstants.REPLY);
		onLineDatabaseConnClient.addPort(onLineDatabaseConnReplyPort);

		// nossTransManagerConn is extensiblePort because transConsistCheck connects NOSS by network
		ConnNossTransManagerConnRequestPort = new ExtensiblePort (PrismConstants.REQUEST);
		ConnNossTransManagerConnRequestPort.addDistribution(new SocketDistribution());           
		onLineDatabaseConnClient.addPort(ConnNossTransManagerConnRequestPort);
		
        // Add the nossTransManagerConn to the c4Architecture
		c4Architecture.add(onLineDatabaseConnClient);
		
		// Weld the request port to the connector reply port.
		c4Architecture.weld(ConnNossTransManagerRequestPort, onLineDatabaseConnReplyPort);    	
		
	/*
	 * Server Setup
	 */
		// Add a port to the transConsistCheck for reply requests.
		Port transConsistCheckReplyPort = new Port(PrismConstants.REPLY);
		transConsistCheckComponent.addPort(transConsistCheckReplyPort);
		
		// Add transConsistCheckComponent to c4Architecture
		c4Architecture.add(transConsistCheckComponent);
		
		// Create a connector(transConsistCheckConn)
		Connector transConsistCheckConnServer = new Connector();
		
		// Add a port to the transConsistCheckConn for forwarding requests.
		Port transConsistCheckConnRequestPort = new Port(PrismConstants.REQUEST);
		transConsistCheckConnServer.addPort(transConsistCheckConnRequestPort);
		
		// transConsistCheckConn is extensiblePort, this checking component has lots of functions
		// because scale easily by adding more servers, also enhance performance
		ExtensiblePort transConsistCheckConnReplyPort = new ExtensiblePort (PrismConstants.REPLY);
		transConsistCheckConnReplyPort.addDistribution(new SocketDistribution(C4Constant.transconsistCheckPort));           
		transConsistCheckConnServer.addPort(transConsistCheckConnReplyPort);
		
        // Add the transConsistCheckConn to the c4Architecture
		c4Architecture.add(transConsistCheckConnServer);
		
		// Weld the request port to the connector reply port.
		c4Architecture.weld(transConsistCheckReplyPort, transConsistCheckConnRequestPort);
	
	/*
	 * Client Setup
	 */
		// Add a port to the transConsistCheck for sending requests.
		Port transConsistCheckRequestPort = new Port(PrismConstants.REQUEST);
		transConsistCheckComponent.addPort(transConsistCheckRequestPort);
        
		// Add a port to the nossTransManagerConn for receiving requests.
		Port nossTransManagerConnReplyPort = new Port(PrismConstants.REPLY);
		nossTransManagerConnClient.addPort(nossTransManagerConnReplyPort);

		// nossTransManagerConn is extensiblePort because transConsistCheck connects NOSS by network
		nossTransManagerConnRequestPort = new ExtensiblePort (PrismConstants.REQUEST);
		nossTransManagerConnRequestPort.addDistribution(new SocketDistribution());           
		nossTransManagerConnClient.addPort(nossTransManagerConnRequestPort);
		
        // Add the nossTransManagerConn to the c4Architecture
		//c4Architecture.add(nossTransManagerConnClient);
		
		// Weld the request port to the connector reply port.
		c4Architecture.weld(transConsistCheckRequestPort, nossTransManagerConnReplyPort);
	/* 
	 * Client Ends
	 */

	}

	
	// this function weld connector to CustomerSupport and TaskProcessorGUI
	// this is private, connecting components is inside job of this instance
	// In other words, this is also initializing, other instances is free to initialize
	private void customerSupportStart() {
		
		//Declare components 
		Component customerSupportComponent = new Component();
		
		// Create Component's implementation  
		CustomerSupport customerSupport = new CustomerSupport();
		
		// Set implementations to its component
		customerSupportComponent.setImplementation(customerSupport);
		
		
	/*
	 * Server Setup
	 */
		// Add a port to the CustomerSupport for reply requests.
		Port customerSupportReplyPort = new Port(PrismConstants.REPLY);
		customerSupportComponent.addPort(customerSupportReplyPort);
		
		// Add customerSupportComponent to c4Architecture
		c4Architecture.add(customerSupportComponent);
		
		// Create a connector(customerSupportConn) for TaskProcessorGUI
		Connector customerSupportConnServer = new Connector();
		
		// Add a port to the customerSupportConn for forwarding requests.
		Port customerSupportConnRequestPort = new Port(PrismConstants.REQUEST);
		customerSupportConnServer.addPort(customerSupportConnRequestPort);
		
		// customerSupportConn is extensiblePort because a terminal of TaskProcessorGUI connects customerSupport by network
		ExtensiblePort customerSupportConnReplyPort = new ExtensiblePort (PrismConstants.REPLY);
		customerSupportConnReplyPort.addDistribution(new SocketDistribution(C4Constant.csPort));           
		customerSupportConnServer.addPort(customerSupportConnReplyPort);
		
        // Add the customerSupportConn to the c4Architecture
		c4Architecture.add(customerSupportConnServer);
	
		// Weld the GUI request port to the connector reply port.
		c4Architecture.weld(customerSupportReplyPort, customerSupportConnRequestPort);
	/*
	 * Client Setup
	 */
		
		// Add a port to the customerSupport for sending requests.
		Port customerSupportRequestPort = new Port(PrismConstants.REQUEST);
		customerSupportComponent.addPort(customerSupportRequestPort);
		
		// Create a connector
		Connector transConsistCheckConnClient = new Connector();

		// Add a port to the transConsistCheckConn for receiving requests.
		Port transConsistCheckConnReplyPort = new Port(PrismConstants.REPLY);
		transConsistCheckConnClient.addPort(transConsistCheckConnReplyPort);

		// transConsistCheckConn is extensiblePort because offLineDatabase connects customerSupport by network
		transConsistCheckConnReplyPortRequestPort = new ExtensiblePort (PrismConstants.REQUEST);
		transConsistCheckConnReplyPortRequestPort.addDistribution(new SocketDistribution());           
		transConsistCheckConnClient.addPort(transConsistCheckConnReplyPortRequestPort);
		
        // Add the transConsistCheckConn to the c4Architecture
		c4Architecture.add(transConsistCheckConnClient);
		
		// Weld the request port to the connector reply port.
		c4Architecture.weld(customerSupportRequestPort, transConsistCheckConnReplyPort);
		
	}
	
}
